package com.ktg.mes.chanjet.spi;

import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSONPObject;
import com.chanjet.openapi.sdk.java.*;
import com.chanjet.openapi.sdk.java.domain.GetAppAccessTokenContent;
import com.chanjet.openapi.sdk.java.domain.GetOrgAccessTokenContent;
import com.chanjet.openapi.sdk.java.domain.GetPermanentAuthCodeContent;
import com.chanjet.openapi.sdk.java.domain.GetTokenByPermanentCodeContent;
import com.chanjet.openapi.sdk.java.exception.ChanjetApiException;
import com.chanjet.openapi.sdk.java.request.*;
import com.chanjet.openapi.sdk.java.response.*;
import com.ktg.common.utils.DateUtils;
import com.ktg.mes.chanjet.common.Constants;
import com.ktg.mes.chanjet.config.OpenApiConfig;
import com.ktg.mes.chanjet.content.DeliveryOrderContent;
import com.ktg.mes.chanjet.content.GetVoucherContent;
import com.ktg.mes.chanjet.content.InventoryClassContent;
import com.ktg.mes.chanjet.request.GetVoucherRequest;
import com.ktg.mes.chanjet.request.InventoryClassRequest;
import com.ktg.mes.chanjet.request.TplusMaterielRequest;
import com.ktg.mes.chanjet.response.GetVoucherResponse;
import com.ktg.mes.chanjet.response.InventoryClassResponse;
import com.ktg.mes.chanjet.response.TplusMaterielResponse;
import com.ktg.mes.chanjet.vo.QueryOrderVo;
import com.ktg.mes.unit.other.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
@Slf4j
public class ChanjetSpi {
    @Autowired
    private OpenApiConfig appConfig;
    @Autowired
    private ChanjetClient chanjetClient;

    @Autowired
    private RedisService redisService;



    /**
     * 获取应用凭证
     * @param getAppAccessTokenContent
     * @return
     * @throws ChanjetApiException
     */
    public GetAppAccessTokenResponse getAppAccessToken(GetAppAccessTokenContent getAppAccessTokenContent) throws ChanjetApiException {
        GetAppAccessTokenRequest getAppAccessTokenRequest = new GetAppAccessTokenRequest();
        getAppAccessTokenRequest.setAppKey(appConfig.getAppKey());
        getAppAccessTokenRequest.setAppSecret(appConfig.getAppSecret());
        getAppAccessTokenRequest.setRequestUri("/auth/appAuth/getAppAccessToken");
        getAppAccessTokenRequest.setBizContent(getAppAccessTokenContent);
        return chanjetClient.execute(getAppAccessTokenRequest);
    }

    /**
     * 获取企业永久授权码
     * @param getPermanentAuthCodeContent
     * @return
     * @throws ChanjetApiException
     */
    public GetPermanentAuthCodeResponse getPermanentAuthCode(GetPermanentAuthCodeContent getPermanentAuthCodeContent) throws ChanjetApiException {
        GetPermanentAuthCodeRequest getPermanentAuthCodeRequest = new GetPermanentAuthCodeRequest();
        getPermanentAuthCodeRequest.setAppKey(appConfig.getAppKey());
        getPermanentAuthCodeRequest.setAppSecret(appConfig.getAppSecret());
        getPermanentAuthCodeRequest.setRequestUri("/auth/orgAuth/getPermanentAuthCode");
        getPermanentAuthCodeRequest.setBizContent(getPermanentAuthCodeContent);
        return chanjetClient.execute(getPermanentAuthCodeRequest);
    }

    /**
     * 获取应用凭证
     * @param getOrgAccessTokenContent
     * @return
     * @throws ChanjetApiException
     */
    public GetOrgAccessTokenResponse getOrgAccessToken(GetOrgAccessTokenContent getOrgAccessTokenContent) throws ChanjetApiException {
        GetOrgAccessTokenRequest getOrgAccessTokenRequest = new GetOrgAccessTokenRequest();
        getOrgAccessTokenRequest.setAppKey(appConfig.getAppKey());
        getOrgAccessTokenRequest.setAppSecret(appConfig.getAppSecret());
        getOrgAccessTokenRequest.setRequestUri("/auth/orgAuth/getOrgAccessToken");
        getOrgAccessTokenRequest.setBizContent(getOrgAccessTokenContent);
        return chanjetClient.execute(getOrgAccessTokenRequest);
    }

    /**
     * 使用code换区openToken
     * @param code
     * @param redirectUri
     * @return
     * @throws ChanjetApiException
     */
    public GetTokenResponse getToken(String code, String redirectUri) throws ChanjetApiException {
        GetTokenRequest getTokenRequest = new GetTokenRequest();
        getTokenRequest.setAppKey(appConfig.getAppKey());
        getTokenRequest.setAppSecret(appConfig.getAppSecret());
        getTokenRequest.setRequestUri("/auth/getToken");
        getTokenRequest.addQueryParam("redirectUri", redirectUri);
        getTokenRequest.addQueryParam("code", code);
        getTokenRequest.addQueryParam("grantType", "authorization_code");
        getTokenRequest.addQueryParam("appKey", appConfig.getAppKey());

        return chanjetClient.execute(getTokenRequest);
    }

    /**
     * 使用用户永久授权码获取openToken
     * @param getTokenByPermanentCodeContent
     * @return
     * @throws ChanjetApiException
     */
    public GetTokenByPermanentCodeResponse getTokenByPermanentCode(GetTokenByPermanentCodeContent getTokenByPermanentCodeContent) throws ChanjetApiException {
        GetTokenByPermanentCodeRequest getTokenByPermanentCodeRequest = new GetTokenByPermanentCodeRequest();
        getTokenByPermanentCodeRequest.setAppKey(appConfig.getAppKey());
        getTokenByPermanentCodeRequest.setAppSecret(appConfig.getAppSecret());
        getTokenByPermanentCodeRequest.setRequestUri("/auth/token/getTokenByPermanentCode");
        getTokenByPermanentCodeRequest.setBizContent(getTokenByPermanentCodeContent);
        return chanjetClient.execute(getTokenByPermanentCodeRequest);
    }

    /**
     * 刷新token
     *
     * @return
     * @throws ChanjetApiException
     */
    public void refreshToken() throws ChanjetApiException {
        RefreshTokenRequest refreshTokenRequest = new RefreshTokenRequest();
        refreshTokenRequest.setAppKey(appConfig.getAppKey());
        refreshTokenRequest.setAppSecret(appConfig.getAppSecret());
        refreshTokenRequest.setContentType("application/json");
        refreshTokenRequest.setRequestUri("/auth/v2/refreshToken");
        refreshTokenRequest.addQueryParam("grantType","refresh_token");
        String refreshToken = redisService.get(Constants.REFRESH_TOKNE);
        refreshTokenRequest.addQueryParam("refreshToken",refreshToken);
        RefreshTokenResponse refreshTokenResponse = chanjetClient.execute(refreshTokenRequest);
        RefreshTokenResponse.Result result = refreshTokenResponse.getResult();
        redisService.add(Constants.CHANJET_TOKEN,result.getAccessToken());
        redisService.add(Constants.REFRESH_TOKNE,result.getRefreshToken());
    }

    /**
     * 获取用户信息
     * @param openToken
     * @return
     * @throws ChanjetApiException
     */
    public UserResponse user(String openToken) throws ChanjetApiException {
        UserRequest userRequest = new UserRequest();
        userRequest.setAppKey(appConfig.getAppKey());
        userRequest.setAppSecret(appConfig.getAppSecret());
        userRequest.setOpenToken(openToken);
        userRequest.setRequestUri("/accounting/cia/api/v1/user");
        return chanjetClient.execute(userRequest);
    }


    /**
     * 存货分类
     * @return
     * @throws ChanjetApiException
     */
    public InventoryClassResponse getInventoryClass() throws ChanjetApiException {
        InventoryClassContent content = new InventoryClassContent();
        InventoryClassRequest request = new InventoryClassRequest();
        initRequest(request,"/tplus/api/v2/inventoryClass/Query");
        JSONObject jsonObject = new JSONObject();
        jsonObject.putOpt("SelectFields","id,code,name,parent.id,parent.code,ts");
        content.setParam(jsonObject);
        request.setBizContent(content);
        return (InventoryClassResponse) chanjetClient.execute(request);
    }

    /**
     * 存货分页查询
     * @param content
     * @return
     * @throws ChanjetApiException
     */
    public TplusMaterielResponse getMaterielPageList(InventoryClassContent content) throws ChanjetApiException {
        TplusMaterielRequest request = new TplusMaterielRequest();
        initRequest(request,"/tplus/api/v2/inventory/QueryPage");
        request.setBizContent(content);
        return chanjetClient.execute(request);
    }


    /**
     * 获取全部存货
     * @param content
     * @return
     * @throws ChanjetApiException
     */
    public InventoryClassResponse getMaterielList(InventoryClassContent content) throws ChanjetApiException {
        InventoryClassRequest request = new InventoryClassRequest();
        initRequest(request,"/tplus/api/v2/inventory/Query");
        request.setBizContent(content);
        return chanjetClient.execute(request);
    }

    /**
     * 根据存货查询计量单位列表
     * @param
     * @return
     * @throws ChanjetApiException
     */
    public InventoryClassResponse getUnitList(String code) throws ChanjetApiException {
        InventoryClassContent content = new InventoryClassContent();
        JSONObject param = new JSONObject();
        param.put("Code",code);
        content.setParam(param);
        InventoryClassRequest request = new InventoryClassRequest();
        initRequest(request,"/tplus/api/v2/inventoryUnit/Query");
        request.setOpenToken(redisService.get(Constants.CHANJET_TOKEN));
        request.setBizContent(content);
        return chanjetClient.execute(request);
    }


    /**
     * 获取销售订单列表
     * @param vo
     * @return
     * @throws ChanjetApiException
     */
    public GetVoucherResponse getOrderList(QueryOrderVo vo) throws ChanjetApiException {
        GetVoucherRequest getVoucherRequest = new GetVoucherRequest();
        initRequest(getVoucherRequest,"/tplus/api/v2/SaleOrderOpenApi/FindVoucherList");
        GetVoucherContent content = new GetVoucherContent();
        content.setPageIndex(vo.getPageIndex() - 1);
        content.setPageSize(vo.getPageSize());
        content.setParamDic(vo.getParamDic());
        List fields = new ArrayList();
        Collections.addAll(fields, "SaleOrder.Code", // 订单编号
                "SaleOrder.Customer.Name",  // 客户
                "SaleOrder.Customer.Code",
                "SaleOrder.VoucherDate",  // 订单日期
                "SaleOrder.Memo",  // 备注
                "SaleOrder.Clerk.Name", // 业务员
                "SaleOrder.Clerk.Code", // 业务员
                "SaleOrder.pubuserdefnvc1",
                "SaleOrder.Ts",
                "SaleOrder.VoucherState.Name",  // 单据状态
                "SaleOrder.SaleOrderAllState", // 执行状态
                "SaleOrder.BusinessType.Name", // 业务类型
                "SaleOrder.ReturnOrderType.Name",  // 售后类型
                "SaleOrder.Customer.PartnerAbbName",  // 客户简称
                "SaleOrder.Currency.Name",  //币种
                "SaleOrder.ReciveType.Name",  // 收款方式
                "SaleOrder.Maker",  //制单人
                "SaleOrder.Auditor",  // 审核人
                "SaleOrder.OrigReceiveAmount", // 预收款
                "SaleOrder.OrigTaxAmount");  // 含税总金额
        content.setSelectFields(fields);
        getVoucherRequest.setBizContent(content);
       return chanjetClient.execute(getVoucherRequest);
    }

    /**
     * 获取订单详情
     * @param vo
     * @return
     * @throws ChanjetApiException
     */
    public GetVoucherResponse getVoucherOrder(QueryOrderVo vo) throws ChanjetApiException {
        GetVoucherRequest getVoucherRequest = new GetVoucherRequest();
        initRequest(getVoucherRequest,"/tplus/api/v2/SaleOrderOpenApi/GetVoucherDTO");
        GetVoucherContent getVoucherContent = new GetVoucherContent();
        JSONObject param = new JSONObject();
        if(vo.getVourcherCode()!= null){
            param.putOpt("voucherCode",vo.getVourcherCode());
        }
        if(vo.getVourcherId() > 0){
            param.putOpt("voucherId",vo.getVourcherId());
        }
        getVoucherContent.setParam(param);
        getVoucherRequest.setBizContent(getVoucherContent);
        return chanjetClient.execute(getVoucherRequest);
    }


    /**
     * 获取库存信息
     * @param content
     * @return
     * @throws ChanjetApiException
     */
    public InventoryClassResponse getStockList(InventoryClassContent content) throws ChanjetApiException {
        InventoryClassRequest request = new InventoryClassRequest();
        initRequest(request,"/tplus/api/v2/currentStock/Query");
        request.setBizContent(content);
        return chanjetClient.execute(request);
    }


    /**
     * 获取仓库信息
     * @return
     * @throws ChanjetApiException
     */
    public InventoryClassResponse getWareHouseList() throws ChanjetApiException {
        InventoryClassContent content = new InventoryClassContent();
        JSONObject param = new JSONObject();
        param.putOpt("SelectFields","ID,Code,Name,Admin,Admin.Name,Memo,Address");
        content.setParam(param);
        InventoryClassRequest request = new InventoryClassRequest();
        initRequest(request,"/tplus/api/v2/warehouse/Query");
        request.setBizContent(content);
        return chanjetClient.execute(request);
    }


    /**
     * 获取采购入库单
     * @param content
     * @return
     * @throws ChanjetApiException
     */
    public GetVoucherResponse findPurchaseReceiveList(GetVoucherContent content) throws ChanjetApiException {
        GetVoucherRequest request = new GetVoucherRequest();
        List selectFields = new ArrayList();
        Collections.addAll(selectFields,
                "RDRecord.Code",
                "RDRecord.VoucherDate",
                "RDRecord.ID",
                "RDRecord.Partner.code",
                "RDRecord.Partner.Name",
                "RDRecord.Partner.PartnerAbbName",
                "RDRecord.PurchaseOrderCode",
                "RDRecord.Memo",
                "RDRecord.VoucherState.Name",
                "RDRecord.Warehouse.Name",
                "RDRecord.RDRecordDetails.Inventory.Name",
                "RDRecord.RDRecordDetails.Inventory.Code",
                "RDRecord.RDRecordDetails.Inventory.Specification",
                "RDRecord.RDRecordDetails.Inventory.priuserdefnvc1",
                "RDRecord.RDRecordDetails.Inventory.priuserdefnvc2",
                "RDRecord.RDRecordDetails.Inventory.priuserdefnvc3",
                "RDRecord.RDRecordDetails.Inventory.priuserdefnvc4",
                "RDRecord.RDRecordDetails.Inventory.priuserdefnvc5",
                "RDRecord.RDRecordDetails.Quantity",
                "RDRecord.RDRecordDetails.Batch",
                "RDRecord.RdStyle.name",
                "RDRecord.RDRecordDetails.Unit.Name",
                "RDRecord.Warehouse.ID",
                "RDRecord.Warehouse.Code",
                "RDRecord.RDRecordDetails.Inventory.ID",
                "RDRecord.RDRecordDetails.ID",
                "RDRecord.Partner.ID");
        content.setSelectFields(selectFields);
        content.setParamDic(content.getParamDic());
        initRequest(request,"/tplus/api/v2/PurchaseReceiveOpenApi/FindVoucherList");
        request.setBizContent(content);
        return chanjetClient.execute(request);
    }

    /**
     * 获取成品入库单
     * @param content
     * @return
     * @throws ChanjetApiException
     */
    public GetVoucherResponse findProductReceiveList(GetVoucherContent content) throws ChanjetApiException {
        GetVoucherRequest request = new GetVoucherRequest();
        List selectFields = new ArrayList();
        Collections.addAll(selectFields,
                "RDRecord.Code",
                "RDRecord.VoucherDate",
                "RDRecord.ID",
                "RDRecord.Partner.code",
                "RDRecord.Partner.Name",
                "RDRecord.Partner.PartnerAbbName",
                "RDRecord.PurchaseOrderCode",
                "RDRecord.Memo",
                "RDRecord.VoucherState.Name",
                "RDRecord.RDRecordDetails.Warehouse.Name",
                "RDRecord.RDRecordDetails.Inventory.Name",
                "RDRecord.RDRecordDetails.Inventory.Code",
                "RDRecord.RDRecordDetails.Inventory.Specification",
                "RDRecord.RDRecordDetails.Inventory.priuserdefnvc1",
                "RDRecord.RDRecordDetails.Inventory.priuserdefnvc2",
                "RDRecord.RDRecordDetails.Inventory.priuserdefnvc3",
                "RDRecord.RDRecordDetails.Inventory.priuserdefnvc4",
                "RDRecord.RDRecordDetails.Inventory.priuserdefnvc5",
                "RDRecord.RDRecordDetails.Quantity",
                "RDRecord.RDRecordDetails.Batch",
                "RDRecord.RdStyle.name",
                "RDRecord.RDRecordDetails.Unit.Name",
                "RDRecord.RDRecordDetails.Warehouse.ID",
                "RDRecord.RDRecordDetails.Warehouse.Code",
                "RDRecord.RDRecordDetails.Inventory.ID",
                "RDRecord.RDRecordDetails.ID",
                "RDRecord.Partner.ID");
        content.setSelectFields(selectFields);
        content.setParamDic(content.getParamDic());
        initRequest(request,"/tplus/api/v2/ProductReceiveOpenApi/FindVoucherList");
        request.setBizContent(content);
        return chanjetClient.execute(request);
    }

    /**
     * 获取采购订单列表
     * @param vo
     * @return
     * @throws ChanjetApiException
     */
    public GetVoucherResponse getPurchaseOrderList(QueryOrderVo vo) throws ChanjetApiException {
        GetVoucherRequest getVoucherRequest = new GetVoucherRequest();
        initRequest(getVoucherRequest,"/tplus/api/v2/PurchaseOrderOpenApi/FindVoucherList");
        GetVoucherContent content = new GetVoucherContent();
        content.setPageIndex(vo.getPageIndex() - 1);
        content.setPageSize(vo.getPageSize());
        content.setParamDic(vo.getParamDic());
        List selectFields = new ArrayList();
        Collections.addAll(selectFields,
                "PurchaseOrder.VoucherState.Name",  //订单状态
                "PurchaseOrder.VoucherDate",   //单据日期
                "PurchaseOrder.Code",   //订单编码
                "PurchaseOrder.ID",
                "PurchaseOrder.Partner.PartnerAbbName",  // 供应商简称
                "PurchaseOrder.AcceptDate",    //  应到货日期
                "PurchaseOrder.Maker",  // 制单人
                "PurchaseOrder.OrigTotalTaxAmount",   //   含税总金额
                "PurchaseOrder.Auditor",
                "PurchaseOrder.PayType.Name",
                "PurchaseOrder.OrigPrePaymentAmount");   // 审核人
        content.setSelectFields(selectFields);
        getVoucherRequest.setBizContent(content);
        return chanjetClient.execute(getVoucherRequest);
    }

    /**
     * 获取采购订单详情
     * @param voucherCode
     * @return
     * @throws ChanjetApiException
     */
    public GetVoucherResponse getPurchaseOrder(String voucherCode) throws ChanjetApiException {
        GetVoucherRequest getVoucherRequest = new GetVoucherRequest();
        initRequest(getVoucherRequest,"/tplus/api/v2/PurchaseOrderOpenApi/GetVoucherDTO");
        GetVoucherContent getVoucherContent = new GetVoucherContent();

        JSONObject param = new JSONObject();
        param.putOpt("voucherCode",voucherCode);
        getVoucherContent.setParam(param);
        getVoucherRequest.setBizContent(getVoucherContent);
        return chanjetClient.execute(getVoucherRequest);
    }


    /**
     * 获取销货单
     * @param vo
     * @return
     * @throws ChanjetApiException
     */
    public GetVoucherResponse getOrderItemList(QueryOrderVo vo) throws ChanjetApiException {
        GetVoucherRequest getVoucherRequest = new GetVoucherRequest();
        List list = new ArrayList();
        Collections.addAll(list,"SaleDelivery.ID",
                "SaleDelivery.VoucherState.Name",
                "SaleDelivery.BusinessType.Name",
                "SaleDelivery.Code",
                "SaleDelivery.Customer.PartnerAbbName",
                "SaleDelivery.InvoiceType.Name",
                "SaleDelivery.VoucherDate",
                "SaleDelivery.Clerk.Name",
                "SaleDelivery.SendPerson.Name",
                "SaleDelivery.SendDate",
                "SaleDelivery.Consignor.Name",
                "SaleDelivery.Maker",
                "SaleDelivery.Auditor",
                "SaleDelivery.OrigTaxAmount",
                "SaleDelivery.SaleDeliveryDetails.SaleDelivery.SaleOrderCode",
                "SaleDelivery.SaleDeliveryDetails.ID",
                "SaleDelivery.SaleDeliveryDetails.Inventory.Code");
        initRequest(getVoucherRequest,"/tplus/api/v2/SaleDeliveryOpenApi/FindVoucherList");
        GetVoucherContent content = new GetVoucherContent();
        content.setPageIndex(vo.getPageIndex() - 1);
        content.setPageSize(vo.getPageSize());
        content.setParamDic(vo.getParamDic());
        content.setSelectFields(vo.getSelectFields());
        getVoucherRequest.setBizContent(content);
        return chanjetClient.execute(getVoucherRequest);
    }


    /**
     * 创建销售出库单
     * @param content
     * @return
     * @throws ChanjetApiException
     */
    public GetVoucherResponse  saleDispatchCreate(DeliveryOrderContent content) throws ChanjetApiException {
        GetVoucherRequest getVoucherRequest = new GetVoucherRequest();
        initRequest(getVoucherRequest,"/tplus/api/v2/SaleDispatchOpenApi/Create");
        getVoucherRequest.setBizContent(content);
        return chanjetClient.execute(getVoucherRequest);
    }

    private void initRequest(AbstractChanjetRequest request, String url){
        request.setAppKey(appConfig.getAppKey());
        request.setRequestUri(url);
        request.setAppSecret(appConfig.getAppSecret());
        request.setContentType("application/json");
        request.setOpenToken(redisService.get(Constants.CHANJET_TOKEN));
    }
    public JSONObject getDateParmDic(){
        Date now = new Date();
        Date date = DateUtils.addDays(now, -90);
        String dateStr = DateUtils.parseDateToStr("yyyy-MM-dd", date);
        String nowStr = DateUtils.parseDateToStr("yyyy-MM-dd", now);
        JSONObject start = new JSONObject();
        start.putOpt("text",dateStr);
        start.putOpt("value",dateStr);
        JSONObject end = new JSONObject();
        end.putOpt("text",nowStr);
        end.putOpt("value",nowStr);
        List datelist = new ArrayList();
        datelist.add(start);
        datelist.add(end);
        JSONObject voucherDate = new JSONObject();
        voucherDate.putOpt("RDRecord.VoucherDate",datelist);
        return voucherDate;
    }

    public Map<String,Object> converData(Map<String,Object> map){
        List<String> columns = (List<String>) map.get("Columns");
        List<List> rows = (List<List>) map.get("Rows");
        List<JSONObject> list = new ArrayList<>();
        for (List row: rows) {
            JSONObject jsonRow = new JSONObject();
            for (int i = 0; i < row.size(); i++) {
                jsonRow.putOpt(columns.get(i),row.get(i));
            }
            list.add(jsonRow);
        }
        map.put("records",list);
        return map;
    }
}
